package logosetter;

import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.ProgressMonitor;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

import org.imgscalr.Scalr;

class LogoSetter extends JFrame implements ActionListener {

    private static final long serialVersionUID = 1754851680025700205L;
    JButton SUBMIT;
    JPanel panel;
    JLabel sourceLocLabel, destinationLocLabel, pngFilePathLabel, imageSizePercentageLabel, attachLogoLabel;
    LongTask task;
    final JTextField sourceLoc, destinationLoc, imageSizePercentage;
    JFileChooser fc = new JFileChooser();
    JButton openButtonSrcLoc, openButtonDestLoc;
    JCheckBox attachLogoCheckBox;
    ProgressMonitor progressMonitor;
    Timer timer;
    int current;
    String statMessage;
    boolean isDone;
    String destinationLocation, sourceLocation;

    public LogoSetter() {
        fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

        task = new LongTask();
        sourceLocLabel = new JLabel();
        sourceLocLabel.setText("Source Location");
        sourceLoc = new JTextField(255);
        // sourceLoc.setText("/media/work/sandbox/cps/source");

        openButtonSrcLoc = new JButton("", createImageIcon("image/open.gif"));
        openButtonSrcLoc.addActionListener(this);

        destinationLocLabel = new JLabel();
        destinationLocLabel.setText("Destination Location");
        destinationLoc = new JTextField(255);
        // destinationLoc.setText("/media/work/sandbox/cps/images");

        openButtonDestLoc = new JButton("", createImageIcon("image/open.gif"));
        openButtonDestLoc.addActionListener(this);

        imageSizePercentageLabel = new JLabel();
        imageSizePercentageLabel.setText("Image Size %");
        imageSizePercentage = new JTextField(2);
        // imageSizePercentage.setText("10");

        SUBMIT = new JButton("Submit");

        panel = new JPanel(new GridLayout(5, 5));
        panel.add(sourceLocLabel);

        JPanel sourcePanel = new JPanel(new GridLayout(1, 2)); // use
                                                               // sourcePanel
                                                               // for layout...
        sourcePanel.add(sourceLoc);
        sourcePanel.add(openButtonSrcLoc);

        panel.add(sourcePanel);

        panel.add(destinationLocLabel);

        JPanel destPanel = new JPanel(new GridLayout(1, 2)); // use sourcePanel
                                                             // for layout...
        destPanel.add(destinationLoc);
        destPanel.add(openButtonDestLoc);

        panel.add(destPanel);

        attachLogoLabel = new JLabel();
        attachLogoLabel.setText("Attach Logo");
        panel.add(attachLogoLabel);
        attachLogoCheckBox = new JCheckBox();
        attachLogoCheckBox.setSelected(true);

        panel.add(attachLogoCheckBox);

        panel.add(imageSizePercentageLabel);
        panel.add(imageSizePercentage);

        panel.add(SUBMIT);
        add(panel, BorderLayout.CENTER);

        SUBMIT.addActionListener(this);
        SUBMIT.setActionCommand("start");

        setTitle("Central Fotoz Logo Setter");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // Create a timer.
        timer = new Timer(1000, new TimerListener());
    }

    public void actionPerformed(ActionEvent ae) {

        if (ae.getSource() == SUBMIT) {
            timer.start();

            sourceLocation = sourceLoc.getText();
            System.out.println("Source Location : " + sourceLocation);
            destinationLocation = destinationLoc.getText();
            System.out.println("Destination Location : " + destinationLocation);
            if (sourceLocation.length() == 0) {
                System.err.println("Please enter source location..");
                JOptionPane.showMessageDialog(this, "Please enter source location..", "Error", JOptionPane.ERROR_MESSAGE);
            } else if (destinationLocation.length() == 0) {
                System.err.println("Please enter destination location..");
                JOptionPane.showMessageDialog(this, "Please enter destination location..", "Error", JOptionPane.ERROR_MESSAGE);
            } else if (imageSizePercentage.getText().length() == 0) {
                System.err.println("Please enter image size percentage..");
                JOptionPane.showMessageDialog(this, "Please enter image size percentage..", "Error", JOptionPane.ERROR_MESSAGE);
            } else {
                task.go();
                SUBMIT.setEnabled(false);
                if (task.isDone()) {
                    JOptionPane.showMessageDialog(this, "Logo has been successfully updated on all images at location :" + destinationLocation,
                            "Success", JOptionPane.INFORMATION_MESSAGE);
                }

            }

        } else if (ae.getSource() == openButtonSrcLoc) {
            int returnVal = fc.showOpenDialog(LogoSetter.this);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                File file = fc.getSelectedFile();
                sourceLoc.setText(file.getAbsolutePath());
                System.out.println("Set Source location .." + file.getAbsolutePath());
            } else {
                System.out.println("Open command cancelled by user..");
            }
        } else if (ae.getSource() == openButtonDestLoc) {
            int returnVal = fc.showOpenDialog(LogoSetter.this);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                File file = fc.getSelectedFile();
                destinationLoc.setText(file.getAbsolutePath());
                System.out.println("Set Destination location .." + file.getAbsolutePath());
            } else {
                System.out.println("Open command cancelled by user..");
            }
        }
    }

    class TimerListener implements ActionListener {
        public void actionPerformed(ActionEvent evt) {
            progressMonitor.setProgress(task.getCurrent());
            String s = task.getMessage();
            if (s != null) {
                progressMonitor.setNote(s);
            }
            if (progressMonitor.isCanceled() || task.isDone()) {
                progressMonitor.close();
                task.stop();
                Toolkit.getDefaultToolkit().beep();
                timer.stop();
                SUBMIT.setEnabled(true);
            }
        }
    }

    protected static ImageIcon createImageIcon(String path) {
        java.net.URL imgURL = LogoSetter.class.getResource(path);
        if (imgURL != null) {
            return new ImageIcon(imgURL);
        } else {
            System.err.println("Couldn't find file: " + path);
            return null;
        }
    }

    class LongTask {
        private int lengthOfTask;
        private int current = 0;
        private boolean done = false;
        private boolean canceled = false;
        private String statMessage;

        public LongTask() {
            // Compute length of task...
            // In a real program, this would figure out
            // the number of bytes to read or whatever.
        }

        /**
         * Called from ProgressBarDemo to start the task.
         */
        public void go() {
            final SwingWorker worker = new SwingWorker() {
                public Object construct() {
                    current = 0;
                    done = false;
                    canceled = false;
                    statMessage = null;
                    return new ActualTask();
                }
            };
            worker.start();
        }

        /**
         * Called from ProgressBarDemo to find out how much work needs to be
         * done.
         */
        public int getLengthOfTask() {
            return lengthOfTask;
        }

        /**
         * Called from ProgressBarDemo to find out how much has been done.
         */
        public int getCurrent() {
            return current;
        }

        public void stop() {
            canceled = true;
            statMessage = null;
        }

        /**
         * Called from ProgressBarDemo to find out if the task has completed.
         */
        public boolean isDone() {
            return done;
        }

        /**
         * Returns the most recent status message, or null if there is no
         * current status message.
         */
        public String getMessage() {
            return statMessage;
        }

        /**
         * The actual long running task. This runs in a SwingWorker thread.
         */
        public class ActualTask {
            ActualTask() {
                int imageSizePer = new Integer(imageSizePercentage.getText()).intValue();
                BufferedImage image = null;
                BufferedImage combined = null;
                BufferedImage overlay = null;
                Graphics graphics = null;
                if (attachLogoCheckBox.isSelected()) {
                    try {
                        InputStream is = ClassLoader.getSystemResourceAsStream("logosetter/image/logo.png");
                        overlay = ImageIO.read(is);
                    } catch (IOException e2) {
                        e2.printStackTrace();
                    }
                }

                File destFolderLoc = new File(destinationLocation);
                if (!destFolderLoc.exists()) {
                    System.out.println("Folder location " + destinationLocation + " doesn't exists!");
                }

                File f = new File(sourceLocation);
                if (f.exists()) {
                    if (f.isDirectory()) {

                        File[] fd = f.listFiles();
                        int totalFiles = fd.length;
                        lengthOfTask = fd.length;
                        if (totalFiles > 0) {
                            progressMonitor = new ProgressMonitor(LogoSetter.this, "Running a Logo Setter", "", 0, totalFiles);
                            progressMonitor.setProgress(0);
                            progressMonitor.setMillisToDecideToPopup(1 * 1000);
                            timer.start();
                        }

                        for (int i = 0; i < fd.length; i++) {
                            if (i == (fd.length - 1)) {
                                done = true;
                                current = lengthOfTask;
                            }
                            if (progressMonitor.isCanceled()) {
                                break;
                            }

                            if (fd[i].isFile()) {
                                if (fd[i].getName().toLowerCase().contains(".jpg") || fd[i].getName().toLowerCase().contains(".jpeg")) {

                                    try {
                                        image = ImageIO.read(new File(sourceLocation, fd[i].getName()));
                                    } catch (IOException e1) {
                                        e1.printStackTrace();
                                    }

                                    int width = image.getWidth() * imageSizePer / 100;
                                    int height = image.getHeight() * imageSizePer / 100;

                                    if (attachLogoCheckBox.isSelected()) {
                                        combined = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
                                        graphics = combined.getGraphics();
                                        graphics.drawImage(image, 0, 0, null);
                                        graphics.drawImage(overlay, 0, 300, null);
                                    } else {
                                        combined = image;
                                    }

                                    try {
                                        BufferedImage thumbnail = Scalr.resize(combined, Scalr.Method.SPEED, Scalr.Mode.FIT_TO_WIDTH, width, height,
                                                Scalr.OP_ANTIALIAS);
                                        ImageIO.write(thumbnail, "JPG", new File(destinationLocation, fd[i].getName()));
                                    } catch (IOException e) {
                                        e.printStackTrace();
                                    }
                                    current = i + 1;
                                    statMessage = "Completed " + current + " out of " + totalFiles + ".";
                                }
                            }
                        }
                    }
                    isDone = true;
                } else {
                    System.out.println("Folder location " + sourceLocation + " doesn't exists!");
                }

            }
        }
    }
}

abstract class SwingWorker {
    private Object value; // see getValue(), setValue()

    private static class ThreadVar {
        private Thread thread;

        ThreadVar(Thread t) {
            thread = t;
        }

        synchronized Thread get() {
            return thread;
        }

        synchronized void clear() {
            thread = null;
        }
    }

    private ThreadVar threadVar;

    /**
     * Get the value produced by the worker thread, or null if it hasn't been
     * constructed yet.
     */
    protected synchronized Object getValue() {
        return value;
    }

    /**
     * Set the value produced by worker thread
     */
    private synchronized void setValue(Object x) {
        value = x;
    }

    /**
     * Compute the value to be returned by the <code>get</code> method.
     */
    public abstract Object construct();

    /**
     * Called on the event dispatching thread (not on the worker thread) after
     * the <code>construct</code> method has returned.
     */
    public void finished() {
    }

    /**
     * A new method that interrupts the worker thread. Call this method to force
     * the worker to stop what it's doing.
     */
    public void interrupt() {
        Thread t = threadVar.get();
        if (t != null) {
            t.interrupt();
        }
        threadVar.clear();
    }

    /**
     * Return the value created by the <code>construct</code> method. Returns
     * null if either the constructing thread or the current thread was
     * interrupted before a value was produced.
     * 
     * @return the value created by the <code>construct</code> method
     */
    public Object get() {
        while (true) {
            Thread t = threadVar.get();
            if (t == null) {
                return getValue();
            }
            try {
                t.join();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt(); // propagate
                return null;
            }
        }
    }

    /**
     * Start a thread that will call the <code>construct</code> method and then
     * exit.
     */
    public SwingWorker() {
        final Runnable doFinished = new Runnable() {
            public void run() {
                finished();
            }
        };

        Runnable doConstruct = new Runnable() {
            public void run() {
                try {
                    setValue(construct());
                } finally {
                    threadVar.clear();
                }

                SwingUtilities.invokeLater(doFinished);
            }
        };

        Thread t = new Thread(doConstruct);
        threadVar = new ThreadVar(t);
    }

    /**
     * Start the worker thread.
     */
    public void start() {
        Thread t = threadVar.get();
        if (t != null) {
            t.start();
        }
    }
}
